﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using Moonlite.Languages.vJass;
using Moonlite.Languages.vJass.CodeObj;
using Moonlite.ExtensionApi;
using Moonlite.ExtensionApi.GlobalInterfaces;
using Moonlite.Platform.General;

namespace Moonlite.Services.CodeCompletion
{
    public static class JassInheritanceManager
    {
        private static Hashtable parsers = new Hashtable();
        private static Hashtable Parsers
        {
            get { return parsers; }
        }

        public static JParser GetParserFromFile(IProjectFile file)
        {
            return GetParserFromFile(file.Path);
        }

        public static JParser GetParserFromFile(string filename)
        {
            return (JParser)Parsers[filename];
        }

        public static JParser GetParserFromLibraryName(string name)
        {
            UpdateFileNames();
            foreach (object parserObject in Parsers.Values)
            {
                JParser parser = (JParser)parserObject;
                foreach (Library library in parser.Libraries)
                {
                    if (library.Name == name)
                    {
                        return parser;
                    }
                }
            }

            return null;
        }

        public static JParser GetParserFromStructName(string name)
        {
            UpdateFileNames();
            foreach (object parserObject in Parsers.Values)
            {
                JParser parser = (JParser)parserObject;
                foreach (Struct @struct in parser.Structs)
                {
                    if (@struct.Name == name)
                    {
                        return parser;
                    }
                }
            }

            return null;
        }

        public static Library GetLibraryFromLibraryName(string name)
        {
            UpdateFileNames();
            foreach (object parserObject in Parsers.Values)
            {
                JParser parser = (JParser)parserObject;
                foreach (Library library in parser.Libraries)
                {
                    if (library.Name == name)
                    {
                        return library;
                    }
                }
            }

            return null;
        }

        public static Struct GetStructFromStructName(string name)
        {
            UpdateFileNames();
            foreach (object parserObject in Parsers.Values)
            {
                JParser parser = (JParser)parserObject;
                foreach (Struct @struct in parser.Structs)
                {
                    if (@struct.Name == name)
                    {
                        return @struct;
                    }
                }
            }

            return null;
        }

        public static void UpdateFileNames()
        {
            List<string> removeInstances = new List<string>();
            foreach (object filenameObject in Parsers.Keys)
            {
                string filename = (string)filenameObject;
                if (File.Exists(filename) == false)
                {
                    removeInstances.Add(filename);
                }
            }

            removeInstances.ForEach(Parsers.Remove);
        }

        public static void UpdateFile(IProjectFile file)
        {
            UpdateFile(file.Path);
        }

        public static void UpdateFile(string filename)
        {
            try
            {
                JParser parser = (JParser)GetParserFromFile(filename);
                if (parser != null)
                {
                    using (StreamReader reader = new StreamReader(filename))
                    {
                        parser.Text = reader.ReadToEnd();
                    }

                    if (string.IsNullOrEmpty(parser.Text) == false && string.IsNullOrEmpty(parser.Text.Trim(' ', '\r', '\n')) == false)
                    {
                        parser.Parse();
                    }
                }
                else if (Parsers.ContainsKey(filename) == false)
                {
                    AddFile(filename);
                }
            }
            catch (Exception exception)
            {
                Logger.Log += exception + Environment.NewLine;
            }
        }

        public static void AddFile(IProjectFile file)
        {
            AddFile(file.Path);
        }

        public static void AddFile(string filename)
        {
            JParser parser = new JParser();
            DirectoryHelper.CreatePath(filename);
            if (File.Exists(filename) != true)
            {
                return;
            }

            using (StreamReader reader = new StreamReader(filename))
            {
                parser.Text = reader.ReadToEnd();
            }

            if (string.IsNullOrEmpty(parser.Text) == false && string.IsNullOrEmpty(parser.Text.Trim(' ', '\r', '\n')) == false)
            {
                parser.Parse();
            }

            if (Parsers.ContainsKey(filename) == true)
            {
                Parsers.Remove(filename);
            }

            Parsers.Add(filename, parser);
        }

        public static void RemoveFile(IProjectFile file)
        {
            RemoveFile(file.Path);
        }

        public static void RemoveFile(string filename)
        {
            Parsers.Remove(filename);
        }

        public static void RemoveAll()
        {
            if (Global.Instance.Project != null)
            {
                RemoveAll(Global.Instance.Project.GetAllFiles());
            }
        }

        private static void RemoveAll(ProjectFileCollection files)
        {
            foreach (IProjectFile file in files)
            {
                RemoveFile(file);
            }
        }

        public static void Update()
        {
            if (Global.Instance.Project != null)
            {
                ProjectFileCollection files = Global.Instance.Project.GetAllFiles();
                RemoveAll(files);
                foreach (IProjectFile file in files)
                {
                    if (Path.GetExtension(file.Path) == Global.JassFileExtension) AddFile(file);
                }
            }
        }
    }
}
